package com.ztesoft.zcm.cmdb.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.ztesoft.zcm.cmdb.constants.Constants;
import com.ztesoft.zcm.cmdb.constants.FileNameMode;
import com.ztesoft.zsmart.core.log.ZSmartLogger;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

@Component("fileUploadHelper")
public class FileUploadHelper {

    private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(FileUploadHelper.class);

    private static final long ONE_SECONDS = 1000;

    private static final String FILE_SEPRATOR = File.separator;

    //public static final String DEFAULT_PATH = "$HOME/upload";
    public static final String DEFAULT_PATH = "E:\\upload";

    private static final String FILE_SUFFIX = ".";

    private static final String FILE_TEMP_LEFT = "(";

    private static final String FILE_TEMP_RIGHT = ")";

    /**
     * 批量上传文件
     * @param request HttpServletRequest
     * @param uploadPath 上传文件的基路径
     * @param fileNameMode 文件命名模式
     * @return
     */
    public JSONArray uploadFile(HttpServletRequest request, String uploadPath, FileNameMode fileNameMode) {
        JSONArray fileArr = new JSONArray();
        long startTime = System.currentTimeMillis();
        LOGGER.info("Start upload file, current time is: {}", DateUtil.getStandardCurrentTime());
        try {
            // 将当前上下文初始化给 CommonsMutipartResolver （多部分解析器）
            CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
                    request.getSession().getServletContext());
            MultipartHttpServletRequest multiRequest = null;
            // 检查form中是否有enctype="multipart/form-data" 并将request变成多部分request
            if (multipartResolver.isMultipart(request)) {
                multiRequest = (MultipartHttpServletRequest) request;
            }
            else {
                multiRequest = multipartResolver.resolveMultipart(request);
            }

            // 获取multiRequest 中所有的文件名
            Iterator<String> iter = multiRequest.getFileNames();
            while (iter.hasNext()) {
                // 一次遍历所有文件
                MultipartFile file = multiRequest.getFile(iter.next());
                JSONObject fileObj = this.createFile(file, uploadPath, fileNameMode);

                fileArr.add(fileObj);
            }
        }
        catch (IOException e) {
            LOGGER.error(e);
        }

        long endTime = System.currentTimeMillis();
        LOGGER.info("End upload file, current time is: {}", DateUtil.getStandardCurrentTime());
        LOGGER.info("Upload file finish, total coast is {} seconds", (endTime - startTime) / ONE_SECONDS);
        LOGGER.info("Upload file List {}", fileArr.toJSONString());
        return fileArr;
    }

    private JSONObject createFile(MultipartFile file, String uploadPath, FileNameMode fileNameMode) throws IOException {
        JSONObject uploadFileObj = null;
        if (null != file) {
            if (StringUtil.isEmpty(uploadPath)) {
                uploadPath = DEFAULT_PATH + FILE_SEPRATOR;
            }

            if (!uploadPath.endsWith(FILE_SEPRATOR)) {
                uploadPath = uploadPath + FILE_SEPRATOR;
            }

            if (createDirectory(uploadPath)) {
                LOGGER.info("Upload file name: {}" + file.getOriginalFilename());
                File newFile = getNewFile(uploadPath, file.getOriginalFilename(), fileNameMode);
                // 上传
                file.transferTo(newFile);
                String newFilePath = newFile.getCanonicalPath();

                uploadFileObj = new JSONObject();
                uploadFileObj.put(Constants.ConstUploadFile.ORIGINAL_FILE_NAME, file.getOriginalFilename());
                uploadFileObj.put(Constants.ConstUploadFile.CURRENT_FILE_NAME, newFile.getName());
                uploadFileObj.put(Constants.ConstUploadFile.CURRENT_FILE_PATH, newFilePath);
            }

        }
        return uploadFileObj;
    }

    /**
     * Description: 创建目录
     * @method createDirectory
     * @param path : 目录路径
     * @author zhang.yi
     * @taskId
     * @return boolean
     * true创建成功，false创建失败 @throws
     */
    public static boolean createDirectory(String path) {
        File uploadPathFile = new File(path);
        boolean isExists = uploadPathFile.exists();
        boolean isDirectory = uploadPathFile.isDirectory();
        if (!isExists || !isDirectory) {
            boolean flag = uploadPathFile.mkdirs();
            if (!flag) {
                LOGGER.error("Create folder {} failed", path);
                return false;
            }
        }
        return true;
    }

    /**
     * Description: 通过文件命名方式，生成新的文件名 @method getNewFile @param path : 文件存放路径，不含文件名，以/结尾 @param originalFileName :
     * 旧文件名 @param fileNameMode : 文件命名方式 @author zhang.yi @taskId @return java.io.File 新文件完整路径 @throws
     */
    public static File getNewFile(String path, String originalFileName, FileNameMode fileNameMode) {
        File newFile = null;
        switch (fileNameMode) {
            case REPLACE:
                newFile = new File(path + originalFileName);
                break;
            case BACKUP:
                File file = new File(path + originalFileName);
                boolean isExists = file.exists();
                if (!isExists) {
                    // 如果文件不存在，不需要重命名
                    newFile = file;
                    // return newFile;
                    break;
                }
                // 如果存在了，则继续命名
                newFile = getBackUpFile(path, originalFileName, 0);
                break;
            case RANDOM:
                String suffix = originalFileName.substring(originalFileName.lastIndexOf(FILE_SUFFIX));
                long now = System.currentTimeMillis();
                newFile = new File(path + now + suffix);
                break;
            default:
                break;
        }
        return newFile;
    }

    /**
     * Description: 生成备份文件，以(+ 数字+ )的方式递增生成文件名
     * @method getBackUpFile
     * @param filePath : 文件存放路径，不含文件名，以/结尾
     * @param originalFileName :旧文件名
     * @param index : 递增索引，从0开始
     * @author zhang.yi
     * @taskId
     * @return java.io.File 新文件完整路径
     * @throws
     */
    public static File getBackUpFile(String filePath, String originalFileName, int index) {
        boolean isExists = true;
        File newFile = null;
        String prefix = originalFileName.substring(0, originalFileName.lastIndexOf(FILE_SUFFIX));
        String suffix = originalFileName.substring(originalFileName.lastIndexOf(FILE_SUFFIX));
        StringBuffer buffer = new StringBuffer();
        while (isExists) {
            index++;
            buffer.append(filePath);
            buffer.append(prefix);
            buffer.append(FILE_TEMP_LEFT);
            buffer.append(index);
            buffer.append(FILE_TEMP_RIGHT);
            buffer.append(suffix);

            newFile = new File(buffer.toString());
            isExists = newFile.exists();
            if (!isExists) {
                return newFile;
            }
            return getBackUpFile(filePath, originalFileName, index);
        }
        return newFile;
    }
}
